package com.mew.chess.core.game.shbz;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.mew.chess.core.common.handler.AbstractEnterExitHandler;
import com.mew.chess.core.common.handler.ChessEEAnnotation;
import com.mew.chess.core.common.handler.ChessPushMessageUtil;
import com.mew.chess.core.common.message.request.EnterGameRequestMessage;

import com.mew.chess.core.game.shbz.game.*;
import com.mew.chess.core.game.shbz.game.common.*;
import com.mew.chess.core.game.shbz.game.message.EnterResponseMessage;
import com.mew.chess.core.game.shbz.game.message.FishCMDMapType;
import com.mew.chess.core.game.shbz.game.message.FishPushMessage;

import com.mew.chess.core.game.shbz.service.ShbzService;
import com.mew.chess.core.game.yxx.game.common.YxxConstantValue;
import com.mew.common.dc.redis.AucRedisService;
import com.mew.common.dc.redis.UserProfileRedisService;
import com.mew.common.entity.game.WinFree;
import com.mew.common.exception.ResponseCode;
import com.mew.common.rest.bo.GameSession;
import com.mew.common.rest.bo.MewSession;
import com.mew.common.rest.game.ChessEnterRoomResponse;

import com.zebra.remoting.protocol.ZebraCommand;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.function.IntFunction;



@ChessEEAnnotation("SHBZ")
@Service
@Slf4j
public class ShbzEEHandler extends AbstractEnterExitHandler {

    @Autowired
    private AucRedisService aucRedisService;
    @Autowired
    private ShbzService shbzService;

    @Autowired
    private UserProfileRedisService userProfileRedisService;
    @Autowired
    private ShbzStartService shbzStartService;

    @Override
    public ResponseCode doSitDown(int roomId, GameSession chessSession, MewSession session, boolean isRepeat) {
        //1 校验
        ShbzRoomManager roomManager = ShbzGameManager.getInstance().getController(roomId);
        if (null == roomManager){
            shbzStartService.initializeRoomManager(chessSession.getGameId(), roomId);
            roomManager = ShbzGameManager.getInstance().getController(roomId);
            if (null == roomManager){
                log.error("FishRoomManager roomId {} is null", roomId);
                return ResponseCode.SysException ;
            }
        }

        //2 坐下 tableId,  seatNo 此游戏没有
        ShbzSeatManager seatManager = backSeatCheck(roomManager, session);

        if (isRepeat && null == seatManager){
            log.error("Reconnect seat is null  u:{} ", session.uid);
            return ResponseCode.LoginUn;
        }

        seatManager = null == seatManager ? entityRoomSitDown(roomManager,session.uid) : seatManager;

        if (null == seatManager){
            log.error("EnterRoom RoomFull error: roomId {} , uid {}", roomId, session.toString());
            return ResponseCode.RoomFull;
        }

        chessSession.setTableId(seatManager.getTableId());
        chessSession.setSeatNo(seatManager.getSeatNo());

        return ResponseCode.Success;
    }


    private ShbzSeatManager backSeatCheck(ShbzRoomManager room, MewSession session){
        if (session.rid == -9){
            ShbzTableManager tableManager = room.getTableByUserId(session.uid);
            if (tableManager != null){
                tableManager.exitGameTable(session.uid);
            }
            return null;
        }

        ShbzTableManager table = room.getTable(session.tid);
        if (null == table){
            log.info("Reconnect table is null：roomInout {}", session.toString());
            return null;
        }

        ShbzSeatManager seat = table.getSeatByUserId(session.uid);
        if (null == seat){
            log.info("Reconnect seat is null：roomInout {}", session.toString());
            return null;
        }
        return seat;
    }

    private ShbzSeatManager entityRoomSitDown(ShbzRoomManager roomManager, long userId){
        return entityRoomSitDownRecursion(roomManager, userId, 0);
    }

    private ShbzSeatManager entityRoomSitDownRecursion(ShbzRoomManager roomManager, long userId, int recursionSize){
        List<Integer> emptyTableId = roomManager.emptyTableId();
        if (null == emptyTableId || emptyTableId.isEmpty()){
            FishTableUtil.buildTable(roomManager, (FishConstantValue.INIT_TABLE_SIZE + recursionSize * 5));
            emptyTableId = roomManager.emptyTableId();
        }

        ShbzTableManager table = roomManager.getTable(emptyTableId.get(RandomUtil.randomInt(0, emptyTableId.size())));
        if (table == null){
            log.error("No Empty table : room {}", roomManager);
            return null;
        }

        List<Integer> emptySeat = table.emptyPlayerSeat();
        Integer seatNo = emptySeat.get(0);
        ShbzSeatManager seat = FishTableUtil.sitDown(seatNo, table, userId, table.getSemaphore());

        if (recursionSize > 100){
            log.error("************** Warning *********** Cycle over 100 : room {}", roomManager);
            return null;
        }

        if (null == seat){
            return entityRoomSitDownRecursion(roomManager, userId, recursionSize+1);
        }
        return seat;
    }

    @Override
    public void doFinish(GameSession chessSession, ZebraCommand command, ChessEnterRoomResponse enterRoomResponse)  {
        ShbzRoomManager roomManager = ShbzGameManager.getInstance().getController(chessSession.getRoomId());
        ShbzTableManager tableManager = roomManager.getTable(chessSession.getTableId());
        if (ResponseCode.Success.code() != enterRoomResponse.getErrorState()){
            log.error("Enter room Error uid {} response {}", chessSession.getUserId(), enterRoomResponse.getErrorState());
            tableManager.standUP((byte) chessSession.getSeatNo());
            command.sendFailureCode(enterRoomResponse.getErrorState());
            return;
        }

        FishUserBO userBO = tableManager.getOnlineUserMap().get(chessSession.getUserId());
        userBO = null == userBO ? new FishUserBO() : userBO;
        userBO.setGameSession(chessSession);
        putWinFree(userBO);

        tableManager.pushOnlineUserMap(userBO);
        //start game
        if (!tableManager.checkIsNoStart()){
            tableManager.startGame();
        }

        EnterResponseMessage enterResponseMessage = buildEnterRoomResponse(userBO, tableManager, roomManager.getBets());
        command.setToken(chessSession.getTk());
        command.sendMessage(enterResponseMessage);
        log.info("Enter room  {}", userBO.toString());
        aucRedisService.chessBetLock(userBO.getUserId(), FishConstantValue.OVER_TIME); //参与

        if (tableManager.getLinkType() > 99){
            //鱼潮
            ChessPushMessageUtil.pushMessage(chessSession, FishCMDMapType.TideStartMessage.code(), tableManager.getTidePushMessage());
            log.info("Enter push tide uid: {} {}", chessSession.getUserId(), tableManager.getTidePushMessage().toString());
            return;
        }


        //普通鱼
        FishBO[] fishBOS = tableManager.getFishMap().values().stream().filter(f->f.getRemainStep()<f.getRuleStep()).toArray(new IntFunction<FishBO[]>() {
            @Override
            public FishBO[] apply(int value) {
                return new FishBO[value];
            }
        });

        if (fishBOS.length>0){
            FishPushMessage fishPushMessage = FishPushMessage.builder().fishBOs(fishBOS).build();
            ChessPushMessageUtil.pushMessage(chessSession,FishCMDMapType.FishPushMessage.code(),fishPushMessage);
        }
    }


    private EnterResponseMessage buildEnterRoomResponse(FishUserBO userBO, ShbzTableManager tableManager, int[] bets){
        EnterResponseMessage response = new EnterResponseMessage();
        response.setScenarioNo(tableManager.getScenarioNo());
        response.setBets(bets);
        response.setUserMessage(userBO);
        response.setUserList(tableManager.getOtherPlayer(userBO.getGameSession().getUserId()));

        return response;
    }

    public void putWinFree(FishUserBO userBO){
        WinFree winFree = userProfileRedisService.getRedisWinfree(userBO.getUserId(),userBO.getRoomId());
        String json = winFree.getJson();
        if (StringUtils.isNotEmpty(json)){
            userBO.setArtillerys(JSON.parseObject(json,int[].class));
        }
        log.info("shbz arti uid:{} 进房间炸弹 ：{}",userBO.getUserId(),json);
    }

    @Override
    public boolean doExitRoom(MewSession session, int roomId) {
        ShbzTableManager table = ShbzGameManager.getInstance().getController(roomId).getTableByUserId(session.uid);
        FishUserBO userBO = table.getOnlineUserMap().get(session.uid);
        log.info("shbz arti uid:{} 出房间炸弹 ：{}",userBO.getUserId(),userBO.getArtillerys());
        log.info("shbz exit uid:{} room:{} table:{},data:{}",session.uid,table.getRoomId(),table.getTableId(),userBO.getFishLogMap());
        shbzService.doPayment(userBO);
        table.exitGameTable(session.uid);

        return false;
    }



}
